package edu.upenn.seas.peerreview.smui
import edu.upenn.seas.peerreview.{Id, Sink}

/**
 * A BSManager coordinates a sequence (1 or more) consecutive games that involve
 * the same set of fixed players.
 */

class BSManager(name: String, var configs: List[GameConfig], protected val numPlayers: Int, 
    myId: Id, t: Sink.T) extends BSHandler(myId, t) {

  implicit def tupleToPoint(tup: (Int, Int)): Point = Point(tup._1, tup._2)
  
  send(Id.coordinatorId, RegisterTournament(name))
  var players : Set[Id] = Set()
  var tournamentRunning = false
  var numPlayerResultsReceived = 0
  
  // Sends the NewGameConfigs to each agent for the next game in the list.
  def broadcastNewGame() : Unit = {
    if (configs == Nil) {
      tournamentRunning = false
      broadcast(null, players, TournamentOver())
      return
    }
    for (id <- players)
      send(id, NewGameConfigs((players - id).toList, 
                               configs.head.boardSize, 
                               configs.head.ships))
    configs = configs.drop(1)
    numPlayerResultsReceived = 0
  }

  def handle (e: Envelope) { 
    val from = e.from
    e.contents match {
      case JoinServer() =>
        if (!tournamentRunning && !players.contains(from)) {
          players += from 
          if (players.size == numPlayers) {
            tournamentRunning = true
            broadcastNewGame()
          }
        } //trying to join server twice, ignored.

      case PlayerResult(hits: Int, sunks: Int, kills: Int, aWinnerIsYou: Boolean) => {
        numPlayerResultsReceived += 1
        println("==[Manager] Results for %s (%s): %d hits, %d sunks, %d kills".format(
            from, if (aWinnerIsYou) "Victorious!" else "Loser.", hits, sunks, kills))
        if (numPlayerResultsReceived == players.size) {
          broadcast(null, players, GameOver())
          broadcastNewGame()
        }
      }

      case LetMeLeave() => if (players.contains(from)) {
        println("==[Manager] %s has abandoned the tournament".format(from))
        broadcast(from, players, PlayerWithdrawal(from))
        players -= from
      }
      
      case _ => 
        println("Coordinator: Unrecognized message")
    }
  }
}

